using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace HslControls
{
	/// <summary>
	/// 一个五子棋的控件，支持人机对战
	/// </summary>
	[Description("五子棋控件，支持人机对战")]
	public class HslGobang : UserControl
	{
		private Point MouseActivePosition = new Point(-1, -1);

		private Point LastPressPosition = new Point(-1, -1);

		private int PawnIndex = 0;

		private bool IsMouseHoverOnChess = true;

		private bool IsGamePlaying = false;

		private GobangPlayer CurrentPlayer = GobangPlayer.Player1;

		private Point LastPointOfPlayerUser = new Point(-1, -1);

		private StringFormat sf = null;

		private GobangPoint[,] main_chess = new GobangPoint[21, 21];

		private ComputerAI computerAI = null;

		/// <summary> 
		/// 必需的设计器变量。
		/// </summary>
		private IContainer components = null;

		private Label label3;

		private CheckBox checkBox2;

		private Button button1;

		private GroupBox groupBox2;

		private CheckBox checkBox1;

		private GroupBox groupBox1;

		private Label label_score_you;

		private Label label_score_computer;

		private Label label2;

		private Label label1;

		private PictureBox pictureBox1;

		private CheckBox checkBox3;

		private GroupBox groupBox3;

		private RadioButton radioButton1;

		/// <summary>
		/// 实例化控件
		/// </summary>
		public HslGobang()
		{
			InitializeComponent();
			sf = new StringFormat();
			sf.Alignment = StringAlignment.Center;
			sf.LineAlignment = StringAlignment.Center;
			SetStyle(ControlStyles.UserPaint | ControlStyles.SupportsTransparentBackColor, value: true);
			SetStyle(ControlStyles.ResizeRedraw, value: true);
			SetStyle(ControlStyles.OptimizedDoubleBuffer, value: true);
			SetStyle(ControlStyles.AllPaintingInWmPaint, value: true);
		}

		/// <summary>
		/// 是否结束游戏的判断。当落子后需要进行判断，无论是电脑玩家，还是用户玩家
		/// </summary>
		/// <param name="x">落子的点位x</param>
		/// <param name="y">落子的点位y</param>
		/// <param name="player">用户</param>
		/// <returns>是否成功</returns>
		private bool IsGameOver(int x, int y, GobangPlayer player)
		{
			int m_lenght = 1;
			for (int k = 0; k < 4; k++)
			{
				m_lenght = 1;
				for (int j = 1; j < 5 && IsPositionHasPawn(k switch
				{
					0 => new Point(x - j, y), 
					1 => new Point(x, y - j), 
					2 => new Point(x - j, y + j), 
					_ => new Point(x - j, y - j), 
				}, player); j++)
				{
					m_lenght++;
				}
				for (int i = 1; i < 5 && IsPositionHasPawn(k switch
				{
					0 => new Point(x + i, y), 
					1 => new Point(x, y + i), 
					2 => new Point(x + i, y - i), 
					_ => new Point(x + i, y + i), 
				}, player); i++)
				{
					m_lenght++;
				}
				if (m_lenght >= 5)
				{
					return true;
				}
				m_lenght = 1;
			}
			return false;
		}

		/// <summary>
		/// 开始游戏
		/// </summary>
		private void StartGame()
		{
			for (int i = 0; i < 21; i++)
			{
				for (int j = 0; j < 21; j++)
				{
					main_chess[i, j].GobangPlayer = GobangPlayer.NonePlayer;
					main_chess[i, j].StepNumber = 0;
					main_chess[i, j].WeightScore = 0;
				}
			}
			IsGamePlaying = true;
			CurrentPlayer = GobangPlayer.NonePlayer;
			PawnIndex = 1;
			if (checkBox2.Checked)
			{
				main_chess[10, 10].StepNumber = PawnIndex++;
				main_chess[10, 10].GobangPlayer = GobangPlayer.Player1;
				LastPressPosition = new Point(10, 10);
			}
			label3.Text = "Waitting";
			pictureBox1.Refresh();
		}

		/// <summary>
		/// 获取背景
		/// </summary>
		/// <returns></returns>
		private Bitmap GetBackgroundImage()
		{
			Bitmap bitmap = new Bitmap(525, 525);
			Graphics g = Graphics.FromImage(bitmap);
			g.Clear(Color.White);
			Pen m_pen = Pens.LightGray;
			for (int i = 10; i <= 510; i += 25)
			{
				g.DrawLine(m_pen, new Point(10, i), new Point(510, i));
				g.DrawLine(m_pen, new Point(i, 10), new Point(i, 510));
			}
			return bitmap;
		}

		/// <summary>
		/// 判断当前的位置是否有落子
		/// </summary>
		/// <param name="x">坐标x</param>
		/// <param name="y">坐标y</param>
		/// <returns>是否的结果</returns>
		private bool IsPositionHasPawn(int x, int y)
		{
			return main_chess[x, y].GobangPlayer != GobangPlayer.NonePlayer;
		}

		/// <summary>
		/// 判断当前的位置是否有指定玩家的落子
		/// </summary>
		/// <param name="x">坐标x</param>
		/// <param name="y">坐标y</param>
		/// <param name="player">指定的玩家</param>
		/// <returns>是否的结果</returns>
		private bool IsPositionHasPawn(int x, int y, GobangPlayer player)
		{
			if (x < 0 || y < 0 || x > 21 || y > 21)
			{
				return false;
			}
			return main_chess[x, y].GobangPlayer == player;
		}

		/// <summary>
		/// 判断当前的位置是否有指定玩家的落子
		/// </summary>
		/// <param name="point">坐标</param>
		/// <param name="player">指定的玩家</param>
		/// <returns>是否的结果</returns>
		private bool IsPositionHasPawn(Point point, GobangPlayer player)
		{
			return IsPositionHasPawn(point.X, point.Y, player);
		}

		/// <summary>
		/// 判断当前的位置是否有落子
		/// </summary>
		/// <param name="point">指定的位置</param>
		/// <returns>是否的结果</returns>
		private bool IsPositionHasPawn(Point point)
		{
			return IsPositionHasPawn(point.X, point.Y);
		}

		private void pictureBox1_Paint(object sender, PaintEventArgs e)
		{
			Graphics g = e.Graphics;
			g.SmoothingMode = SmoothingMode.HighQuality;
			for (int i = 0; i < 21; i++)
			{
				for (int j = 0; j < 21; j++)
				{
					int m_x = i * 25 + 10;
					int m_y = (20 - j) * 25 + 10;
					if (main_chess[i, j].GobangPlayer == GobangPlayer.NonePlayer)
					{
						if (checkBox3.Checked)
						{
							Rectangle m_rect2 = new Rectangle(m_x - 20, m_y - 10, 40, 20);
							using Font font = new Font("Microsoft YaHei UI", 8f);
							g.DrawString(main_chess[i, j].WeightScore.ToString(), font, Brushes.Gray, m_rect2, sf);
						}
						continue;
					}
					Rectangle m_rect = new Rectangle(m_x - 10, m_y - 10, 20, 20);
					g.FillEllipse(main_chess[i, j].GetPawnBrush, m_rect);
					g.DrawEllipse(Pens.DimGray, m_rect);
					m_rect.Offset(-10, 0);
					m_rect.Width += 20;
					if (checkBox1.Checked)
					{
						using Font fontSmall = new Font("Microsoft YaHei UI", 8f);
						g.DrawString(main_chess[i, j].StepNumber.ToString(), fontSmall, Brushes.White, m_rect, sf);
					}
				}
			}
			if (IsMouseHoverOnChess)
			{
				PaintMarkPoint(g, MouseActivePosition);
			}
			if (!checkBox1.Checked)
			{
				PaintMarkPoint(g, LastPressPosition);
			}
		}

		/// <summary>
		/// 将鼠标光标的坐标转换成棋子的坐标信息
		/// </summary>
		/// <param name="picture_x">鼠标位置 x</param>
		/// <param name="picture_y">mouse point y</param>
		/// <returns>数据点位信息</returns>
		private Point MouseMovePoint(int picture_x, int picture_y)
		{
			int m_x = picture_x / 25;
			int m_y = picture_y / 25;
			m_y = 20 - m_y;
			return new Point(m_x, m_y);
		}

		private void PaintMarkPoint(Graphics g, Point point)
		{
			if (point.X >= 0)
			{
				int m_x = point.X * 25 + 10;
				int m_y = (20 - point.Y) * 25 + 10;
				Pen pen = Pens.LightGray;
				if (main_chess[point.X, point.Y].GobangPlayer == GobangPlayer.Player1)
				{
					pen = Pens.Red;
				}
				g.DrawLines(pen, new Point[3]
				{
					new Point(m_x - 3, m_y - 9),
					new Point(m_x - 3, m_y - 3),
					new Point(m_x - 9, m_y - 3)
				});
				g.DrawLines(pen, new Point[3]
				{
					new Point(m_x - 3, m_y + 9),
					new Point(m_x - 3, m_y + 3),
					new Point(m_x - 9, m_y + 3)
				});
				g.DrawLines(pen, new Point[3]
				{
					new Point(m_x + 3, m_y - 9),
					new Point(m_x + 3, m_y - 3),
					new Point(m_x + 9, m_y - 3)
				});
				g.DrawLines(pen, new Point[3]
				{
					new Point(m_x + 3, m_y + 9),
					new Point(m_x + 3, m_y + 3),
					new Point(m_x + 9, m_y + 3)
				});
			}
		}

		private void HslGobang_Load(object sender, EventArgs e)
		{
			for (int i = 0; i < 21; i++)
			{
				for (int j = 0; j < 21; j++)
				{
					main_chess[i, j] = new GobangPoint();
				}
			}
			computerAI = new ComputerAI(main_chess);
			pictureBox1.Image = GetBackgroundImage();
		}

		private void pictureBox1_MouseLeave(object sender, EventArgs e)
		{
			MouseActivePosition = new Point(-1, -1);
			pictureBox1.Refresh();
		}

		private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
		{
			if (e.X % 25 > 20 || e.X > 520 || e.Y % 25 > 20 || e.Y > 520)
			{
				IsMouseHoverOnChess = false;
				pictureBox1.Refresh();
			}
			else
			{
				MouseActivePosition = MouseMovePoint(e.X, e.Y);
				IsMouseHoverOnChess = !IsPositionHasPawn(MouseActivePosition);
				pictureBox1.Refresh();
			}
		}

		private void button1_Click(object sender, EventArgs e)
		{
			StartGame();
		}

		private void SetPointPawn(Point point, GobangPlayer player)
		{
			main_chess[point.X, point.Y].GobangPlayer = player;
			main_chess[point.X, point.Y].StepNumber = PawnIndex++;
			LastPressPosition = point;
			CurrentPlayer = player;
			if (player == GobangPlayer.Player1)
			{
				computerAI.CalculateAllPoints();
			}
		}

		private void pictureBox1_Click(object sender, EventArgs e)
		{
			if (!IsGamePlaying)
			{
				return;
			}
			Point point_origin = pictureBox1.PointToClient(Cursor.Position);
			if (point_origin.X % 25 > 20 || point_origin.X > 520 || point_origin.Y % 25 > 20 || point_origin.Y > 520)
			{
				return;
			}
			Point point = MouseMovePoint(point_origin.X, point_origin.Y);
			if (IsPositionHasPawn(point) || CurrentPlayer == GobangPlayer.Player2)
			{
				return;
			}
			SetPointPawn(point, GobangPlayer.Player2);
			LastPointOfPlayerUser = point;
			if (IsGameOver(point.X, point.Y, GobangPlayer.Player2))
			{
				IsGamePlaying = false;
				label3.Text = "You Win";
				label_score_you.Text = (Convert.ToInt32(label_score_you.Text) + 1).ToString();
				return;
			}
			label3.Text = "Thinking";
			label3.Refresh();
			Point computer = computerAI.CalculateComputerAI();
			SetPointPawn(computer, GobangPlayer.Player1);
			if (IsGameOver(computer.X, computer.Y, GobangPlayer.Player1))
			{
				label3.Text = "You lose";
				IsGamePlaying = false;
				label_score_computer.Text = (Convert.ToInt32(label_score_computer.Text) + 1).ToString();
			}
			else
			{
				label3.Text = "waitting";
			}
			pictureBox1.Refresh();
		}

		private void checkBox1_CheckedChanged(object sender, EventArgs e)
		{
			pictureBox1.Refresh();
		}

		private void checkBox3_CheckedChanged(object sender, EventArgs e)
		{
			pictureBox1.Refresh();
		}

		/// <summary> 
		/// 清理所有正在使用的资源。
		/// </summary>
		/// <param name="disposing">如果应释放托管资源，为 true；否则为 false。</param>
		protected override void Dispose(bool disposing)
		{
			if (disposing && components != null)
			{
				components.Dispose();
			}
			base.Dispose(disposing);
		}

		/// <summary> 
		/// 设计器支持所需的方法 - 不要修改
		/// 使用代码编辑器修改此方法的内容。
		/// </summary>
		private void InitializeComponent()
		{
			label3 = new System.Windows.Forms.Label();
			checkBox2 = new System.Windows.Forms.CheckBox();
			button1 = new System.Windows.Forms.Button();
			groupBox2 = new System.Windows.Forms.GroupBox();
			checkBox3 = new System.Windows.Forms.CheckBox();
			checkBox1 = new System.Windows.Forms.CheckBox();
			groupBox1 = new System.Windows.Forms.GroupBox();
			label_score_you = new System.Windows.Forms.Label();
			label_score_computer = new System.Windows.Forms.Label();
			label2 = new System.Windows.Forms.Label();
			label1 = new System.Windows.Forms.Label();
			pictureBox1 = new System.Windows.Forms.PictureBox();
			groupBox3 = new System.Windows.Forms.GroupBox();
			radioButton1 = new System.Windows.Forms.RadioButton();
			groupBox2.SuspendLayout();
			groupBox1.SuspendLayout();
			((System.ComponentModel.ISupportInitialize)pictureBox1).BeginInit();
			groupBox3.SuspendLayout();
			SuspendLayout();
			label3.Font = new System.Drawing.Font("等线 Light", 36f, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 134);
			label3.ForeColor = System.Drawing.Color.Blue;
			label3.Location = new System.Drawing.Point(553, 317);
			label3.Name = "label3";
			label3.Size = new System.Drawing.Size(240, 95);
			label3.TabIndex = 14;
			label3.Text = "Playing";
			label3.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
			checkBox2.AutoSize = true;
			checkBox2.Checked = true;
			checkBox2.CheckState = System.Windows.Forms.CheckState.Checked;
			checkBox2.Font = new System.Drawing.Font("微软雅黑", 9f, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 134);
			checkBox2.Location = new System.Drawing.Point(556, 437);
			checkBox2.Name = "checkBox2";
			checkBox2.Size = new System.Drawing.Size(173, 21);
			checkBox2.TabIndex = 12;
			checkBox2.Text = "Computer First [电脑先手]";
			checkBox2.UseVisualStyleBackColor = true;
			button1.Font = new System.Drawing.Font("微软雅黑", 9f, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 134);
			button1.Location = new System.Drawing.Point(556, 464);
			button1.Name = "button1";
			button1.Size = new System.Drawing.Size(237, 52);
			button1.TabIndex = 11;
			button1.Text = "Start Game [开始游戏]";
			button1.UseVisualStyleBackColor = true;
			button1.Click += new System.EventHandler(button1_Click);
			groupBox2.Controls.Add(checkBox3);
			groupBox2.Controls.Add(checkBox1);
			groupBox2.Font = new System.Drawing.Font("微软雅黑", 9f, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 134);
			groupBox2.Location = new System.Drawing.Point(556, 87);
			groupBox2.Name = "groupBox2";
			groupBox2.Size = new System.Drawing.Size(237, 76);
			groupBox2.TabIndex = 10;
			groupBox2.TabStop = false;
			groupBox2.Text = "Settings [游戏设置]";
			checkBox3.AutoSize = true;
			checkBox3.Location = new System.Drawing.Point(19, 45);
			checkBox3.Name = "checkBox3";
			checkBox3.Size = new System.Drawing.Size(154, 21);
			checkBox3.TabIndex = 2;
			checkBox3.Text = "Show score [显示得分]";
			checkBox3.UseVisualStyleBackColor = true;
			checkBox3.CheckedChanged += new System.EventHandler(checkBox3_CheckedChanged);
			checkBox1.AutoSize = true;
			checkBox1.Location = new System.Drawing.Point(19, 22);
			checkBox1.Name = "checkBox1";
			checkBox1.Size = new System.Drawing.Size(147, 21);
			checkBox1.TabIndex = 0;
			checkBox1.Text = "Show step [显示步序]";
			checkBox1.UseVisualStyleBackColor = true;
			checkBox1.CheckedChanged += new System.EventHandler(checkBox1_CheckedChanged);
			groupBox1.Controls.Add(label_score_you);
			groupBox1.Controls.Add(label_score_computer);
			groupBox1.Controls.Add(label2);
			groupBox1.Controls.Add(label1);
			groupBox1.Font = new System.Drawing.Font("微软雅黑", 9f, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 134);
			groupBox1.Location = new System.Drawing.Point(556, 3);
			groupBox1.Name = "groupBox1";
			groupBox1.Size = new System.Drawing.Size(237, 78);
			groupBox1.TabIndex = 9;
			groupBox1.TabStop = false;
			groupBox1.Text = "Score [比分]";
			label_score_you.ForeColor = System.Drawing.Color.FromArgb(192, 0, 192);
			label_score_you.Location = new System.Drawing.Point(155, 46);
			label_score_you.Name = "label_score_you";
			label_score_you.Size = new System.Drawing.Size(64, 17);
			label_score_you.TabIndex = 3;
			label_score_you.Text = "0";
			label_score_you.TextAlign = System.Drawing.ContentAlignment.TopRight;
			label_score_computer.ForeColor = System.Drawing.Color.FromArgb(192, 0, 192);
			label_score_computer.Location = new System.Drawing.Point(155, 24);
			label_score_computer.Name = "label_score_computer";
			label_score_computer.Size = new System.Drawing.Size(64, 17);
			label_score_computer.TabIndex = 2;
			label_score_computer.Text = "0";
			label_score_computer.TextAlign = System.Drawing.ContentAlignment.TopRight;
			label2.AutoSize = true;
			label2.ForeColor = System.Drawing.Color.FromArgb(192, 0, 192);
			label2.Location = new System.Drawing.Point(16, 46);
			label2.Name = "label2";
			label2.Size = new System.Drawing.Size(97, 17);
			label2.TabIndex = 1;
			label2.Text = "You [用户玩家] :";
			label1.AutoSize = true;
			label1.ForeColor = System.Drawing.Color.FromArgb(192, 0, 192);
			label1.Location = new System.Drawing.Point(16, 24);
			label1.Name = "label1";
			label1.Size = new System.Drawing.Size(133, 17);
			label1.TabIndex = 0;
			label1.Text = "Computer [电脑玩家] :";
			pictureBox1.BackColor = System.Drawing.Color.White;
			pictureBox1.Location = new System.Drawing.Point(3, 8);
			pictureBox1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
			pictureBox1.Name = "pictureBox1";
			pictureBox1.Size = new System.Drawing.Size(530, 522);
			pictureBox1.TabIndex = 8;
			pictureBox1.TabStop = false;
			pictureBox1.Click += new System.EventHandler(pictureBox1_Click);
			pictureBox1.Paint += new System.Windows.Forms.PaintEventHandler(pictureBox1_Paint);
			pictureBox1.MouseLeave += new System.EventHandler(pictureBox1_MouseLeave);
			pictureBox1.MouseMove += new System.Windows.Forms.MouseEventHandler(pictureBox1_MouseMove);
			groupBox3.Controls.Add(radioButton1);
			groupBox3.Font = new System.Drawing.Font("微软雅黑", 9f, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 134);
			groupBox3.Location = new System.Drawing.Point(556, 169);
			groupBox3.Name = "groupBox3";
			groupBox3.Size = new System.Drawing.Size(237, 145);
			groupBox3.TabIndex = 15;
			groupBox3.TabStop = false;
			groupBox3.Text = "Game Level [游戏级别]";
			radioButton1.AutoSize = true;
			radioButton1.Checked = true;
			radioButton1.Location = new System.Drawing.Point(19, 22);
			radioButton1.Name = "radioButton1";
			radioButton1.Size = new System.Drawing.Size(160, 21);
			radioButton1.TabIndex = 0;
			radioButton1.TabStop = true;
			radioButton1.Text = "simple by author [简单]";
			radioButton1.UseVisualStyleBackColor = true;
			base.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
			BackColor = System.Drawing.Color.Transparent;
			base.Controls.Add(groupBox3);
			base.Controls.Add(label3);
			base.Controls.Add(checkBox2);
			base.Controls.Add(button1);
			base.Controls.Add(groupBox2);
			base.Controls.Add(groupBox1);
			base.Controls.Add(pictureBox1);
			base.Name = "HslGobang";
			base.Size = new System.Drawing.Size(810, 543);
			base.Load += new System.EventHandler(HslGobang_Load);
			groupBox2.ResumeLayout(false);
			groupBox2.PerformLayout();
			groupBox1.ResumeLayout(false);
			groupBox1.PerformLayout();
			((System.ComponentModel.ISupportInitialize)pictureBox1).EndInit();
			groupBox3.ResumeLayout(false);
			groupBox3.PerformLayout();
			ResumeLayout(false);
			PerformLayout();
		}
	}
}
